<template>
  <div class="mapchart">

  </div>
</template>

<script lang="ts">
import { computed, defineComponent, inject, nextTick, onMounted, PropType, ref, Ref, watch } from 'vue'
import { upperFirst } from 'lodash'
import tinycolor from 'tinycolor2'
import Chartist, {
  IChartistLineChart,
  IChartistBarChart,
  IChartistPieChart,
  ILineChartOptions,
  IBarChartOptions,
  IPieChartOptions,
} from 'chartist'
import { ChartData, ChartType, antvChartData } from '@/types/slides'
import { useMainStore, useSlidesStore } from '@/store'
import { storeToRefs } from 'pinia'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'

import 'chartist/dist/scss/chartist.scss'
import { createRandomCode } from '@/utils/common'
import { Scene, PolygonLayer, LineLayer, PointLayer, EarthLayer  } from '@antv/l7';
import { GaodeMap, Earth } from '@antv/l7-maps';

export default defineComponent({
  name: 'chart',
  props: {
    width: {
      type: Number,
      required: true,
    },
    height: {
      type: Number,
      required: true,
    },
    type: {
      type: String as PropType<ChartType>,
      required: true,
    },
    data: {
      type: Object as PropType<antvChartData>,
      required: true,
    },
    options: {
      type: Object as PropType<ILineChartOptions & IBarChartOptions & IPieChartOptions>,
    },
    themeColor: {
      type: Array as PropType<string[]>,
      required: true,
    },
    // legends: {
    //   type: Array as PropType<string[]>,
    //   required: true,
    // },
    gridColor: {
      type: String,
    },
    legend: {
      type: String as PropType<'' | 'top' | 'bottom'>,
    },
    id: {
      type: String,
    }
  },
  setup(props) {
    const slidesStore = useSlidesStore()
    const chartRef = ref<HTMLElement>()
    const slideScale: Ref<number> = inject('slideScale') || ref(1)
    const mainStore = useMainStore()
    const { handleElement, handleElementId } = storeToRefs(mainStore)
    const { addHistorySnapshot } = useHistorySnapshot()
    // const { DataView } = DataSet;
    // let chart: IChartistLineChart | IChartistBarChart | IChartistPieChart | undefined
    let charts: any
    let scene: any
    const chartHeight = computed(() => {
      if (props.legend) return props.height - 20
      return props.height
    })

    // const getDataAndOptions = () => {
    //   const propsOptopns = props.options || {}
    //   const options = {
    //     ...propsOptopns,
    //     width: props.width * slideScale.value,
    //     height: chartHeight.value * slideScale.value,
    //   }
    //   const data = props.type === 'pie' ? { ...props.data, series: props.data.series[0] } : props.data
    //   return { data, options }
    // }

    watch(() => chartHeight.value,
      (val) => {
        // charts.changeSize(props.width * slideScale.value, chartHeight.value * slideScale.value)
      })
    const mapList = [
      {
        center: [ 116.368652, 39.93866 ],
        zoom: 10.07,
        style: 'blank',
        url1: 'https://gw.alipayobjects.com/os/basement_prod/972566c5-a2b9-4a7e-8da1-bae9d0eb0117.json',
        colorlist: [
          '#816CAD',
          '#A67FB5',
          '#C997C7',
          '#DEB8D4',
          '#F5D4E6',
          '#FAE4F1',
          '#FFF3FC'
        ]
      },
      {
        center: [ 116.368652, 39.93866 ],
        zoom: 10.07,
        style: 'blank',
        url1: 'https://gw.alipayobjects.com/os/bmw-prod/94763191-2816-4c1a-8d0d-8bcf4181056a.json',
        colorlist: [
          '#87CEFA',
          '#00BFFF',

          '#7FFFAA',
          '#00FF7F',
          '#32CD32',

          '#F0E68C',
          '#FFD700',

          '#FF7F50',
          '#FF6347',
          '#FF0000'
        ]
      },
      {
        center: [ -96, 37.8 ],
        zoom: 3,
        style: 'light',
        url1: 'https://gw.alipayobjects.com/os/bmw-prod/ecd1aaac-44c0-4232-b66c-c0ced76d5c7d.json',
        url2: 'https://gw.alipayobjects.com/os/bmw-prod/d434cac3-124e-4922-8eed-ccde01674cd3.json',
        colorlist: ['rgb(255,255,217)', 'rgb(237,248,177)', 'rgb(199,233,180)', 'rgb(127,205,187)', 'rgb(65,182,196)', 'rgb(29,145,192)', 'rgb(34,94,168)', 'rgb(12,44,132)' ]
      },
      {
        center: [ 116.368652, 39.93866 ],
        zoom: 8,
        style: 'light',
        url1: 'https://gw.alipayobjects.com/os/bmw-prod/efef6c2b-2922-4c03-b9e0-d3743f68eaf2.json',
      }
    ]
    const renderChart = () => {
      const currentElement = document.querySelector('#editable-element-'+props.id) as HTMLElement
      const parent = currentElement.querySelector('.mapchart') as HTMLElement
      const html = document.createElement('div')
      const id = createRandomCode(3)
      html.setAttribute('id',id)
      html.setAttribute('class', 'chart')
      
      html.style.width = props.width + 'px'
      html.style.height = chartHeight.value + 'px'
      parent.appendChild(html)

      let mapdata: any = {
        url1: 'https://gw.alipayobjects.com/os/basement_prod/972566c5-a2b9-4a7e-8da1-bae9d0eb0117.json',  
      }
      if(props.data.type.type == '3DMAP1'){
        mapdata = mapList[0]
        const scene = new Scene({
          id: id,
          map: new GaodeMap({
            pitch: 0,
            style: 'dark',
            center: [ 114.050008, 22.529272 ],
            zoom: 14.1
          })
        });
        scene.on('loaded', () => {
          fetch(
            mapdata.url1
          )
            .then(res => res.json())
            .then(data => {
              const layer = new PolygonLayer({})
                .source(data)
                .shape('extrude')
                .size('h20', [ 100, 120, 160, 200, 260, 500 ])
                .color('h20', mapdata.colorlist)
                .style({
                  opacity: 1.0
                });
              scene.addLayer(layer);
            });
        });
      }
      if(props.data.type.type == '3DMAP2'){
        mapdata = mapList[1]
        const scene = new Scene({
          id: id,
          map: new GaodeMap({
            style: 'dark',
            pitch: 50,
            center: [ 118.8, 32.056 ],
            zoom: 10
          })
        });
        const colors = mapdata.colorlist;
        scene.on('loaded', () => {
          fetch(
            mapdata.url1
          )
            .then(res => res.json())
            .then(data => {
              const filllayer = new PolygonLayer({
                name: 'fill',
                zIndex: 3
              })
                .source(data)
                .shape('extrude')
                .color('unit_price', colors)
                .size('unit_price', unit_price => unit_price * 50)
                .style({
                  opacity: [ 'unit_price', [ 0, 1 ]],
                  pickLight: true
                })
                .active(true);
              scene.addLayer(filllayer);
            });
        });
      }
      if(props.data.type.type == '3DMAP3'){
        mapdata = mapList[2]
        const scene = new Scene({
          id: id,
          map: new GaodeMap({
            style: 'dark',
            center: [ 120, 29.732983 ],
            zoom: 6.2,
            pitch: 60
          })
        });
        scene.on('loaded', () => {
          let lineDown: any,
            lineUp: any,
            textLayer: any;

          fetch('https://gw.alipayobjects.com/os/bmw-prod/ecd1aaac-44c0-4232-b66c-c0ced76d5c7d.json')
            .then(res => res.json())
            .then(data => {
              const texts: any = [];

              data.features.map((option: any) => {
                const { name, center } = option.properties;
                const [ lng, lat ] = center;
                texts.push({ name, lng, lat });
                return '';
              });

              textLayer = new PointLayer({ zIndex: 2 })
                .source(texts, {
                  parser: {
                    type: 'json',
                    x: 'lng',
                    y: 'lat'
                  }
                })
                .shape('name', 'text')
                .size(14)
                .color('#0ff')
                .style({
                  textAnchor: 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
                  spacing: 2, // 字符间距
                  padding: [ 1, 1 ], // 文本包围盒 padding [水平，垂直]，影响碰撞检测结果，避免相邻文本靠的太近
                  stroke: '#0ff', // 描边颜色
                  strokeWidth: 0.2, // 描边宽度
                  raisingHeight: 200000 + 150000 + 10000,
                  textAllowOverlap: true
                });
              scene.addLayer(textLayer);

              lineDown = new LineLayer()
                .source(data)
                .shape('line')
                .color('#0DCCFF')
                .size(1)
                .style({
                  raisingHeight: 200000
                });

              lineUp = new LineLayer({ zIndex: 1 })
                .source(data)
                .shape('line')
                .color('#0DCCFF')
                .size(1)
                .style({
                  raisingHeight: 200000 + 150000
                });

              scene.addLayer(lineDown);
              scene.addLayer(lineUp);
              return '';
            });

          fetch('https://gw.alipayobjects.com/os/bmw-prod/d434cac3-124e-4922-8eed-ccde01674cd3.json')
            .then(res => res.json())
            .then(data => {
              const lineLayer = new LineLayer()
                .source(data)
                .shape('wall')
                .size(150000)
                .style({
                  heightfixed: true,
                  opacity: 0.6,
                  sourceColor: '#0DCCFF',
                  targetColor: 'rbga(255,255,255, 0)'
                });
              scene.addLayer(lineLayer);

              const provincelayer = new PolygonLayer({})
                .source(data)
                .size(150000)
                .shape('extrude')
                .color('#0DCCFF')
                .active({
                  color: 'rgb(100,230,255)'
                })
                .style({
                  heightfixed: true,
                  pickLight: true,
                  raisingHeight: 200000,
                  opacity: 0.8
                });

              scene.addLayer(provincelayer);

              provincelayer.on('mousemove', () => {
                provincelayer.style({
                  raisingHeight: 200000 + 100000
                });
                lineDown.style({
                  raisingHeight: 200000 + 100000
                });
                lineUp.style({
                  raisingHeight: 200000 + 150000 + 100000
                });
                textLayer.style({
                  raisingHeight: 200000 + 150000 + 10000 + 100000
                });
              });

              provincelayer.on('unmousemove', () => {
                provincelayer.style({
                  raisingHeight: 200000
                });
                lineDown.style({
                  raisingHeight: 200000
                });
                lineUp.style({
                  raisingHeight: 200000 + 150000
                });
                textLayer.style({
                  raisingHeight: 200000 + 150000 + 10000
                });
              });
              return '';
            });
          return '';
        });
      }
      if(props.data.type.type == '3DMAP4'){
        mapdata = mapList[3]
        const scene = new Scene({
          id: id,
          map: new Earth({})
        });

        const earthlayer = new EarthLayer()
          .source(
            'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ',
            {
              parser: {
                type: 'image'
              }
            }
          )
          .shape('base')
          .style({
            opacity: 1.0,
            radius: 40,
            globelOtions: {
              ambientRatio: 0.6, // 环境光
              diffuseRatio: 0.4, // 漫反射
              specularRatio: 0.1 // 高光反射
            }
          })
          .animate(true);

        const atomLayer = new EarthLayer()
          .color('#2E8AE6')
          .shape('atomSphere')
          .style({
            opacity: 1
          });

        const bloomLayer = new EarthLayer().color('#fff').shape('bloomSphere')
          .style({
            opacity: 0.6
          });

        scene.on('loaded', () => {
          scene.addLayer(earthlayer);
          fetch('https://gw.alipayobjects.com/os/bmw-prod/efef6c2b-2922-4c03-b9e0-d3743f68eaf2.json')
            .then(res => res.json())
            .then(data => {
              const pointlayer = new PointLayer()
                .source(data,
                  {
                    parser: {
                      type: 'json',
                      x: 'lng',
                      y: 'lat'
                    }
                  }
                )
                .shape('circle')
                .color('#f00')
                .size(10)
                .active(true);
              scene.addLayer(pointlayer);
            });

          scene.addLayer(atomLayer);
          scene.addLayer(bloomLayer);

          earthlayer.setEarthTime(4.0);
        });
      }
      
     
    }

    const updateChart = () => {
      if (!charts) {
        return
      }
      if (props.id != handleElement.value?.id) {
        return
      }
      // const { data, options } = getDataAndOptions()

      if (handleElement.value?.type == 'chart' && handleElement.value?.data) {
        let s = handleElement.value?.data.type.s;
        let x = handleElement.value?.data.type.x;
        let y = handleElement.value?.data.type.y;
        let data = handleElement.value?.data.data;
        charts.changeData(data);

        console.log("updateChart", s, x, y)

        // renderChart()
      }
      // chart.update(data, options)
    }

    watch([
      () => props.width,
      () => props.height,
      () => props.data,
      slideScale,
    ], updateChart)

    onMounted(renderChart)

    const themeColors = computed(() => {
      let colors: string[] = []
      if (props.themeColor.length >= 10) colors = props.themeColor
      else if (props.themeColor.length === 1) colors = tinycolor(props.themeColor[0]).analogous(10).map(color => color.toHexString())
      else {
        const len = props.themeColor.length
        const supplement = tinycolor(props.themeColor[len - 1]).analogous(10 + 1 - len).map(color => color.toHexString())
        colors = [...props.themeColor.slice(0, len - 1), ...supplement]
      }

      return colors
    })

    // 更新主题配色：
    // 如果当前所设置的主题色数小于10，剩余部分获取最后一个主题色的相近颜色作为配色
    const updateTheme = () => {
      if (!chartRef.value) return

      for (let i = 0; i < 10; i++) {
        chartRef.value.style.setProperty(`--theme-color-${i + 1}`, themeColors.value[i])
      }
      
      const props: any = {
        themeColor: themeColors,
      }
      // slidesStore.updateElement({ id: handleElementId.value, props })
      addHistorySnapshot()
    }

    watch(themeColors, updateTheme)
    // onMounted(updateTheme)

    // 更新网格颜色，包括坐标的文字部分
    const updateGridColor = () => {
      if (!chartRef.value) return
      if (props.gridColor) chartRef.value.style.setProperty(`--grid-color`, props.gridColor)
    }

    watch(() => props.gridColor, updateGridColor)
    onMounted(updateGridColor)

    return {
      chartHeight,
      themeColors,
      slideScale,
      chartRef,
      DataView,
      handleElement,
      handleElementId,
    }
  },
})
</script>

<style lang="scss" scoped>
.chart {
  display: flex;
}

.chart-content {
  transform-origin: 0 0;
}
</style>

<style lang="scss">
.l7-ctrl-logo {
  display: none;
}
.chart-content {
  $ct-series-names: (a, b, c, d, e, f, g, h, i, j);

  --theme-color-1: #666;
  --theme-color-2: #666;
  --theme-color-3: #666;
  --theme-color-4: #666;
  --theme-color-5: #666;
  --theme-color-6: #666;
  --theme-color-7: #666;
  --theme-color-8: #666;
  --theme-color-9: #666;
  --theme-color-10: #666;

  @for $i from 1 to length($ct-series-names) {
    $color: var(--theme-color-#{$i});

    .ct-series-#{nth($ct-series-names, $i)} .ct-line {
      stroke: $color;
    }

    .ct-series-#{nth($ct-series-names, $i)} .ct-point {
      stroke: $color;
    }

    .ct-series-#{nth($ct-series-names, $i)} .ct-area {
      fill: $color;
    }

    .ct-series-#{nth($ct-series-names, $i)} .ct-bar {
      stroke: $color;
    }

    .ct-series-#{nth($ct-series-names, $i)} .ct-slice-pie {
      fill: $color;
    }

    .ct-series-#{nth($ct-series-names, $i)} .ct-slice-donut {
      stroke: $color;
    }
  }

  --grid-color: rgba(0, 0, 0, 0.4);

  .ct-grid {
    stroke: var(--grid-color);
  }

  .ct-label {
    fill: var(--grid-color);
    color: var(--grid-color);
  }
}

.legends {
  height: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 14px;
}

.legend {
  display: flex;
  align-items: center;

  &+.legend {
    margin-left: 10px;
  }

  .block {
    width: 10px;
    height: 10px;
    margin-right: 5px;
  }
}
</style>